package.cpath = "luaclib/?.so"

local socket = require "client.socket"
local crypt  = require "client.crypt"
local cjson  = require "cjson"

if _VERSION ~= "Lua 5.4" then
    error "Use lua 5.4"
end

local fd = assert(socket.connect("127.0.0.1", 8001))

local function writeline(fd, text)
    socket.send(fd, text .. "\n")
end

local function unpack_line(text)
    local from = text:find("\n", 1, true)
    if from then
        return text:sub(1, from-1), text:sub(from+1)
    end
    return nil, text
end

local last = ""

local function unpack_f(f)
    local function try_recv(fd, last)
        local result
        result, last = f(last)
        if result then
            return result, last
        end
        local r = socket.recv(fd)
        if not r then
            return nil, last
        end
        if r == "" then
            error "Server closed"
        end
        return f(last .. r)
    end

    return function()
        while true do
            local result
            result, last = try_recv(fd, last)
            if result then
                return result
            end
            socket.usleep(100)
        end
    end
end

local readline = unpack_f(unpack_line)

local challenge = crypt.base64decode(readline())

local clientkey = crypt.randomkey()
-- print("clientkey",clientkey)

print("crypt.dhexchange(clientkey)=",crypt.base64encode(crypt.dhexchange(clientkey)))
writeline(fd, crypt.base64encode(crypt.dhexchange(clientkey)))
local secret = crypt.dhsecret(crypt.base64decode(readline()), clientkey)

print("sceret is ", crypt.hexencode(secret))

local hmac = crypt.hmac64(challenge, secret)
writeline(fd, crypt.base64encode(hmac))

local token = {
    server = "sample",
    user = "hello",
    pass = "123456",
}

local function encode_token(token)
    return string.format("%s@%s:%s",
    crypt.base64encode(token.user),
    crypt.base64encode(token.server),
    crypt.base64encode(token.pass))
end

local etoken = crypt.desencode(secret, encode_token(token))
local b = crypt.base64encode(etoken)
writeline(fd, crypt.base64encode(etoken))

local result = readline()
print(result)
local code = tonumber(string.sub(result, 1, 3))
assert(code == 200)
socket.close(fd)

local subid = crypt.base64decode(string.sub(result, 5))

print("login ok, subid=", subid)

----- connect to game server

local function send_request(v, session)
    local size = #v + 4
    local package = string.pack(">I2", size)..v..string.pack(">I4", session)
    socket.send(fd, package)
    return v, session
end

local function recv_response(v)
    local size = #v - 5
    local content, ok, session = string.unpack("c"..tostring(size).."B>I4", v)
    return ok ~=0 , content, session
end

local function unpack_package(text)
    local size = #text
    if size < 2 then
        return nil, text
    end
    local s = text:byte(1) * 256 + text:byte(2)
    if size < s+2 then
        return nil, text
    end

    return text:sub(3,2+s), text:sub(3+s)
end

local readpackage = unpack_f(unpack_package)

local function send_package(fd, pack)
    local package = string.pack(">s2", pack)
    socket.send(fd, package)
end

local text = "echo"
local index = 1

print("connect to game server")
fd = assert(socket.connect("127.0.0.1", 8888))
last = ""

--local handshake = string.format("%s@%s#%s:%d", crypt.base64encode(token.user), crypt.base64encode(token.server),crypt.base64encode(subid) , index)
--local hmac = crypt.hmac64(crypt.hashkey(handshake), secret)

local login_cmd = {
    c="login",
    m="login",
    data={
        id="hello",
        secret=secret,
        subid=subid,
    }
}

local s = cjson.encode(login_cmd)
print("send cmd is ",s)

send_package(fd,s)
print("<===",recv_response(readpackage()))

--send_package(fd, handshake .. ":" .. crypt.base64encode(hmac))

-- print(readpackage())
-- print("===>",send_request(text,0))
-- -- don't recv response
-- -- print("<===",recv_response(readpackage()))

-- print("disconnect")
-- socket.close(fd)

-- index = index + 1

-- print("connect again")
-- fd = assert(socket.connect("127.0.0.1", 8888))
-- last = ""

-- local handshake = string.format("%s@%s#%s:%d", crypt.base64encode(token.user), crypt.base64encode(token.server),crypt.base64encode(subid) , index)
-- local hmac = crypt.hmac64(crypt.hashkey(handshake), secret)

-- send_package(fd, handshake .. ":" .. crypt.base64encode(hmac))

-- print(readpackage())
-- print("===>",send_request("fake",0))	-- request again (use last session 0, so the request message is fake)
-- print("===>",send_request("again",1))	-- request again (use new session)
-- print("<===",recv_response(readpackage()))
-- print("<===",recv_response(readpackage()))


-- print("disconnect")
-- socket.close(fd)

